package com.vast.admin.controller;

import com.google.gson.Gson;
import com.vast.admin.annotation.PassToken;
import com.vast.admin.api.WechatApi;
import com.vast.admin.api.entity.RealNameByFaceVerify;
import com.vast.admin.api.response.RealNameByFaceResponse;
import com.vast.admin.api.response.RealNameByIdentity4Response;
import com.vast.admin.entity.Customer;
import com.vast.admin.entity.WechatContract;
import com.vast.admin.entity.weChat.*;
import com.vast.admin.service.ContractService;
import com.vast.admin.service.CustomerService;
import com.vast.admin.service.WechatCallbackService;
import com.vast.common.constant.MessageCode;
import com.vast.common.core.domain.Result;
import com.vast.system.exception.BusinessException;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Base64Utils;
import org.springframework.web.bind.annotation.*;

import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.Map;

/**
 * 微信回调接口
 */
@Slf4j
@RestController
@RequestMapping("/manager/wx")
public class WechatController {

    @Autowired
    private WechatApi wechatApi;

    @Autowired
    private CustomerService customerService;

    @Autowired
    private WechatCallbackService wechatCallbackService;

    @Autowired
    private ContractService contractService;

    /**
     * 回调接口
     * @param signature
     * @param timestamp
     * @param nonce
     * @param echostr
     * @return
     */
    @GetMapping("/test")
    public Result<Void> test(String signature, String timestamp, String nonce, String echostr) {

        return Result.SUCCESS;
    }

    /**
     * 微信公众号页面获取acesstoken
     * @param code
     * @return
     */
    @GetMapping("/getAcessToken")
    public Result<String> getAcessToken(@NotNull String code) {
        return new Result<>(MessageCode.SUCCESS, wechatApi.getWebAcessToken(code));
    }

    /**
     * 绑定微信id 注册客户信息
     * @param customer
     * @return
     */
    @ApiOperation(value = "绑定微信id 注册客户信息", notes = "绑定微信id 注册客户信息")
    @PassToken
    @PostMapping("/register")
    public Result<Void> register(@RequestBody Customer customer) {
        customerService.addCustomer(customer);
        return Result.SUCCESS;
    }

    /**
     * 获取微信注册用户
     * @param wxId
     * @return
     */
    @GetMapping("/getWxCustomerByWxId")
    public Result<WxCustomer> getWxCustomerByWxId(@NotNull String wxId) {
        Customer customer = customerService.getCustomerByWxId(wxId);
        if (customer == null) {
            return Result.SUCCESS;
        }
        WxCustomer wxCustomer = new WxCustomer();
        BeanUtils.copyProperties(customer, wxCustomer);
        return new Result<>(MessageCode.SUCCESS, wxCustomer);
    }

    /**
     * 获取实名认证状态
     * @param wxId
     * @return
     */
    @GetMapping("/getRealnameStatus")
    public Result<Integer> getRealnameStatus(@NotNull String wxId) {
        Customer customer = customerService.getCustomerByWxId(wxId);
        if (customer == null) {
            return new Result<>(MessageCode.ERROR, "用户未注册");
        }
        return new Result<>(MessageCode.SUCCESS, customer.getRealnameStatus());
    }

//    /**
//     * 申请上上签证书
//     * @param wxId
//     * @return
//     */
//    @ApiOperation(value = "申请上上签证书", notes = "申请上上签证书")
//    @PassToken
//    @GetMapping("/applyCert")
//    public Result<Void> applyCert(String wxId) {
//        customerService.applyCert(wxId);
//        return Result.SUCCESS;
//    }

    /**
     * 银行卡四要素实名认证 返回验证的key 在验证接口中传入
     * @param wxRealNameByIdentity4
     * @return
     */
    @ApiOperation(value = "银行卡四要素实名认证 优先使用银行卡四要素", notes = "银行卡四要素实名认证")
    @PassToken
    @PostMapping("/realNameByIdentity4")
    public Result<RealNameByIdentity4Response> realNameByIdentity4(@RequestBody WxRealNameByIdentity4 wxRealNameByIdentity4) {
        return new Result<>(MessageCode.SUCCESS,customerService.realNameByIdentity4(wxRealNameByIdentity4));
    }

    /**
     * 银行卡四要素实名认证 短信验证码校验及结果
     * @param wxRealNameIdentity4Verify
     * @return
     */
    @ApiOperation(value = "银行卡四要素实名认证 短信验证码校验及结果", notes = "银行卡四要素实名认证 短信验证码校验及结果")
    @PassToken
    @PostMapping("/realNameIdentity4Verify")
    public Result<Void> realNameIdentity4Verify(@RequestBody WxRealNameIdentity4Verify wxRealNameIdentity4Verify) {
        return customerService.realNameIdentity4Verify(wxRealNameIdentity4Verify);
    }


    /**
     * 手机号三要素实名认证 返回验证的key 在验证接口中传入
     * @param wxRealNameByIdentity3
     * @return
     */
    @ApiOperation(value = "手机号三要素实名认证 其次使用手机号三要素", notes = "手机号三要素实名认证")
    @PassToken
    @PostMapping("/realNameByIdentity3")
    public Result<String> realNameByIdentity3(@RequestBody WxRealNameByIdentity3 wxRealNameByIdentity3) {
        return new Result<>(MessageCode.SUCCESS,customerService.realNameByIdentity3(wxRealNameByIdentity3));
    }

    /**
     * 手机号三要素实名认证 短信验证码校验及结果
     * @param wxRealNameIdentity4Verify
     * @return
     */
    @ApiOperation(value = "手机号三要素实名认证 短信验证码校验及结果", notes = "手机号三要素实名认证")
    @PassToken
    @PostMapping("/realNameIdentity3Verify")
    public Result<Void> realNameIdentity3Verify(@RequestBody WxRealNameIdentity4Verify wxRealNameIdentity4Verify) {
        return customerService.realNameIdentity3Verify(wxRealNameIdentity4Verify);
    }

    /**
     * 刷脸认证
     * @param wxRealNameByFace
     * @return
     */
    @ApiOperation(value = "刷脸认证", notes = "刷脸认证")
    @PassToken
    @PostMapping("/realNameByFace")
    public Result<RealNameByFaceResponse> realNameByFace(@RequestBody WxRealNameByFace wxRealNameByFace) {
        return new Result<>(MessageCode.SUCCESS, customerService.realNameByFace(wxRealNameByFace));
    }

    /**
     * 刷脸认证结果 上上签回调接口
     * @param data
     * @return
     */
    @ApiOperation(value = "刷脸认证结果 上上签回调接口", notes = "刷脸认证结果 上上签回调接口")
    @PassToken
    @PostMapping("/realNameByFaceVerify")
    public Result<Void> realNameByFaceVerify(String data) {
        try {
            RealNameByFaceVerify realNameByFaceVerify = new Gson().fromJson(new String(Base64Utils.decodeFromString(data)), RealNameByFaceVerify.class);
            if (customerService.realNameByFaceVerify(realNameByFaceVerify)) {
                return new Result<>(MessageCode.SUCCESS, "认证成功！");
            } else {
                return new Result<>(MessageCode.SUCCESS, "认证失败！");
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return new Result<>(MessageCode.SUCCESS, "认证失败！");
        }
    }

    @ApiOperation(value = "获取合同信息", notes = "获取合同信息")
    @GetMapping("/getContractInfo")
    @PassToken
    public Result<WxContractDto> getContractInfo(Long contractId, String wxId) {
        return new Result<>(MessageCode.SUCCESS, wechatCallbackService.getContractInfo(contractId, wxId));
    }

    @GetMapping("/prePay")
    public Result<Map<String, String>> prePay(Long contractId, String wxId) {
        return new Result<>(MessageCode.SUCCESS, wechatCallbackService.prePay(contractId, wxId));
    }



    /**
     * 支付成功回调：
     * <xml><appid><![CDATA[wx60df5c0505fe8568]]></appid>
     * <bank_type><![CDATA[CMB_DEBIT]]></bank_type>
     * <cash_fee><![CDATA[1]]></cash_fee>
     * <fee_type><![CDATA[CNY]]></fee_type>
     * <is_subscribe><![CDATA[Y]]></is_subscribe>
     * <mch_id><![CDATA[1538604801]]></mch_id>
     * <nonce_str><![CDATA[vrDSRA1jKcamrydfiZ9royLgoBy15XGr]]></nonce_str>
     * <openid><![CDATA[occQ_1IotCjvQfAoViGbHgEfmWes]]></openid>
     * <out_trade_no><![CDATA[ZFW-HB-WH-20201578331618758]]></out_trade_no>
     * <result_code><![CDATA[SUCCESS]]></result_code>
     * <return_code><![CDATA[SUCCESS]]></return_code>
     * <sign><![CDATA[8062FDADEA1119F8A0B51253AB5EA6C2]]></sign>
     * <time_end><![CDATA[20200107012703]]></time_end>
     * <total_fee>1</total_fee>
     * <trade_type><![CDATA[JSAPI]]></trade_type>
     * <transaction_id><![CDATA[4200000483202001073048750060]]></transaction_id>
     * </xml>
     * @param callbackStr
     * 小程序ID	appid	是	String(32)	wx8888888888888888	微信分配的小程序ID
     * 商户号	mch_id	是	String(32)	1900000109	微信支付分配的商户号
     * 设备号	device_info	否	String(32)	013467007045764	微信支付分配的终端设备号，
     * 随机字符串	nonce_str	是	String(32)	5K8264ILTKCH16CQ2502SI8ZNMTM67VS	随机字符串，不长于32位
     * 签名	sign	是	String(32)	C380BEC2BFD727A4B6845133519F3AD6	签名，详见签名算法
     * 签名类型	sign_type	否	String(32)	HMAC-SHA256	签名类型，目前支持HMAC-SHA256和MD5，默认为MD5
     * 业务结果	result_code	是	String(16)	SUCCESS	SUCCESS/FAIL
     * 错误代码	err_code	否	String(32)	SYSTEMERROR	错误返回的信息描述
     * 错误代码描述	err_code_des	否	String(128)	系统错误	错误返回的信息描述
     * 用户标识	openid	是	String(128)	wxd930ea5d5a258f4f	用户在商户appid下的唯一标识
     * 是否关注公众账号	is_subscribe	是	String(1)	Y	用户是否关注公众账号，Y-关注，N-未关注
     * 交易类型	trade_type	是	String(16)	JSAPI	JSAPI、NATIVE、APP
     * 付款银行	bank_type	是	String(32)	CMC	银行类型，采用字符串类型的银行标识，银行类型见银行列表
     * 订单金额	total_fee	是	Int	100	订单总金额，单位为分
     * 应结订单金额	settlement_total_fee	否	Int	100	应结订单金额=订单金额-非充值代金券金额，应结订单金额<=订单金额。
     * 货币种类	fee_type	否	String(8)	CNY	货币类型，符合ISO4217标准的三位字母代码，默认人民币：CNY，其他值列表详见货币类型
     * 现金支付金额	cash_fee	是	Int	100	现金支付金额订单现金支付金额，详见支付金额
     * 现金支付货币类型	cash_fee_type	否	String(16)	CNY	货币类型，符合ISO4217标准的三位字母代码，默认人民币：CNY，其他值列表详见货币类型
     * 总代金券金额	coupon_fee	否	Int	10	代金券金额<=订单金额，订单金额-代金券金额=现金支付金额，详见支付金额
     * 代金券使用数量	coupon_count	否	Int	1	代金券使用数量
     * 代金券类型	coupon_type_$n	否	String	CASH
     * CASH--充值代金券
     * NO_CASH---非充值代金券
     *
     * 并且订单使用了免充值券后有返回（取值：CASH、NO_CASH）。$n为下标,从0开始编号，举例：coupon_type_0
     *
     * 注意：只有下单时订单使用了优惠，回调通知才会返回券信息。
     * 下列情况可能导致订单不可以享受优惠：可能情况。
     * 代金券ID	coupon_id_$n	否	String(20)	10000	代金券ID,$n为下标，从0开始编号
     * 注意：只有下单时订单使用了优惠，回调通知才会返回券信息。
     * 下列情况可能导致订单不可以享受优惠：可能情况。
     * 单个代金券支付金额	coupon_fee_$n	否	Int	100	单个代金券支付金额,$n为下标，从0开始编号
     * 微信支付订单号	transaction_id	是	String(32)	1217752501201407033233368018	微信支付订单号
     * 商户订单号	out_trade_no	是	String(32)	1212321211201407033568112322	商户系统内部订单号，要求32个字符内，只能是数字、大小写字母_-|*@ ，且在同一个商户号下唯一。
     * 商家数据包	attach	否	String(128)	123456	商家数据包，原样返回
     * 支付完成时间	time_end	是	String(14)	20141030133525	支付完成时间，格式为yyyyMMddHHmmss，如2009年12月25日9点10分10秒表示为20091225091010。其他详见时间规则
     * https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7&index=8
     * @return
     */
    @PostMapping("/callback")
    public String callback(@RequestBody String callbackStr) {
        wechatCallbackService.save(callbackStr);
        return "<xml>" +
                "  <return_code><![CDATA[SUCCESS]]></return_code>" +
                "  <return_msg><![CDATA[OK]]></return_msg>" +
                "</xml>";
    }

    /**
     *
     * 退款成功回调：
     * <xml>
     *     <return_code>SUCCESS</return_code>
     *     <appid>
     *         <![CDATA[wx60df5c0505fe8568]]>
     *     </appid>
     *     <mch_id>
     *         <![CDATA[1538604801]]>
     *     </mch_id>
     *     <nonce_str>
     *         <![CDATA[0386c8d7947def0c6eb5e25b7064060f]]>
     *     </nonce_str>
     *     <req_info>
     *         <![CDATA[WMXGjGwO0YHjhkFDKoSlwJWJ44xhsVonYRvTSmIbNJsa2UvW8YYLKFqsh6Ecibt/oMnhgybmD7Ho1RfLHdjyY9/SMDrdxLwDz84F5DYZwH6iHBEc5Fogs3KFJk/29qccrL+iSDN5y/AQN0L8auDXpHo4piQJkMYVbfL3L6X0ydkIBwK7VMrwLM1Kg7k0FGfQzx/MwxONXtlJemWBCaSfs2n3PcE0VqxFyfPRjmkasg8XkD7wq3MnW3dEq7frXfan/j+KqrFrXr0zKJp7NvhtSgTW3fu/cE1WZZIHWGHz/XiRFB1SQA0/0tu6KaaxCI+QtGs3lD9yfaekOmOkJwE2dUB4HI7pSdN1ZSorPX1iMmPf1dHQgXUQZW/zP58WRmWs1RwrcsOZlhdjhIb+f6C5V9htR1wes5zGlVDb37QJ01E20tF/1MtEI3nCskauJ1GR58tgEHOLDl74pmnD6dZ/BMnOYkocFzufTkaPMxezu74WDWP6koFO0GMXXRV1CD6F6IEtu5bJHQY+sUv/s1td+R9NXiD7zDaKn6D2EM5tljypnpM98kZI1EgVEXCfctCVw0amnN307d39eD06ZZ0dIqMxl2m7woTsRtH7pdDVuE2XKXc0eNrZdcPnii7iXTvVh1yM+wC+AeqT3xPB1jz+2qENJABpPw9afd2zNd+BJ+FA0CN5NYX6QZn1HCH5ExJsjtpAinH84yuX8bfD9FW8XFaOU4Rk3bnq9ibcSc7/D53dIVvB964KzvlznjObs0hqj9t3oI3eiQeudeqjnv42O/Q3Rvg+l0fk1k29FwsFSRNdM96rT5rOq1sRdDuWo1kM1lVSzjSWh5ZugWi6j/JBVwIFga7ZIqh+JpkxnLmirwqAmvqg6JxVu53vRm/+OKg1LagB9lqzr4plsdXdbklNuoHUE9igprJiPrnaK6T/awCZvAWBnXVDm8c66NkwTxBlI31dOEF6iqCC9JEUMrIdsfeT3JSI0uHdyLHRuDLTPpmdonXreYCIPUhfZuUDF7yzqdn1oB8fA8NraH7M3NDHtMAUcQM/YNCGTpDAUdE6CmtUdq7LcbwQgGt2v0zxWosx]]>
     *     </req_info>
     * </xml>
     * @param callbackStr
     * 以下为返回的加密字段 req_info：
     * 解密步骤如下：
     * （1）对加密串A做base64解码，得到加密串B
     * （2）对商户key做md5，得到32位小写key* ( key设置路径：微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置 )
     *
     * （3）用key*对加密串B做AES-256-ECB解密（PKCS7Padding）
     *
     * 微信订单号 transaction_id 是 String(32) 1217752501201407033233368018 微信订单号
     *
     * 商户订单号 out_trade_no 是 String(32) 1217752501201407033233368018 商户系统内部的订单号
     *
     * 微信退款单号 refund_id 是 String(32) 1217752501201407033233368018 微信退款单号
     *
     * 商户退款单号 out_refund_no 是 String(64) 1217752501201407033233368018 商户退款单号
     *
     * 订单金额 total_fee 是 Int 100 订单总金额，单位为分，只能为整数，详见支付金额
     *
     * 应结订单金额 settlement_total_fee 否 Int 100 当该订单有使用非充值券时，返回此字段。应结订单金额=订单金额-非充值代金券金额，应结订单金额<=订单金额。
     *
     * 申请退款金额 refund_fee 是 Int 100 退款总金额,单位为分
     *
     * 退款金额 settlement_refund_fee 是 Int 100 退款金额=申请退款金额-非充值代金券退款金额，退款金额<=申请退款金额
     *
     * 退款状态 refund_status 是 String(16) SUCCESS SUCCESS-退款成功 CHANGE-退款异常 REFUNDCLOSE—退款关闭
     *
     * 退款成功时间 success_time 否 String(20) 2017-12-15 09:46:01 资金退款至用户帐号的时间，格式2017-12-15 09:46:01
     *
     * 退款入账账户 refund_recv_accout 是 String(64) 招商银行信用卡0403
     * 取当前退款单的退款入账方
     *
     * 1）退回银行卡：
     *
     * {银行名称}{卡类型}{卡尾号}
     *
     * 2）退回支付用户零钱:
     *
     * 支付用户零钱
     *
     * 3）退还商户:
     *
     * 商户基本账户
     *
     * 商户结算银行账户
     *
     * 4）退回支付用户零钱通:
     *
     * 支付用户零钱通
     *
     * 退款资金来源 refund_account 是  String(30) REFUND_SOURCE_RECHARGE_FUNDS REFUND_SOURCE_RECHARGE_FUNDS 可用余额退款/基本账户 REFUND_SOURCE_UNSETTLED_FUNDS 未结算资金退款
     *
     * 退款发起来源 refund_request_source 是 String(30) API API接口 VENDOR_PLATFORM商户平台
     * https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_16&index=10
     * @return
     */
    @PostMapping("/refundCallback")
    public String refundCallback(@RequestBody String callbackStr) {
        wechatCallbackService.refundCallback(callbackStr);
        return "<xml>" +
                "  <return_code><![CDATA[SUCCESS]]></return_code>" +
                "  <return_msg><![CDATA[OK]]></return_msg>" +
                "</xml>";
    }

    /**
     * 人脸识别结果
     * @param orderNo
     * @param sid
     * @return
     */
    @GetMapping("/getFaceResult")
    public Result<Void> getFaceResult(String orderNo, String sid) {
        return customerService.getFaceResult(orderNo, sid);
    }

    /**
     * 获取已签署的合同列表
     * @param wxId
     * @return
     */
    @GetMapping("/getContractList")
    public Result<List<WechatContract>> getContractList(String wxId) {
        return new Result<>(MessageCode.SUCCESS, contractService.getContractListByWxId(wxId));
    }

    /**
     * 获取合同预览页
     * @param wxId
     * @param contractId
     * @return
     */
    @GetMapping("/getContractPreviewUrl")
    public Result<String> getContractPreviewUrl(String wxId, Long contractId) {
        return new Result<>(MessageCode.SUCCESS, "获取成功", contractService.getContractPreviewUrlByWxId(wxId, contractId));
    }

    /**
     * 判断用户是否关注
     * @param wxId
     * @return
     */
    @GetMapping("/isSubscribe")
    public Result<Boolean> isSubscribe(String wxId) {
        return new Result<>(MessageCode.SUCCESS, customerService.isSubscribe(wxId));
    }

}
